/* File : SODxml.c */

#include "tinyxml2.h"
#include "SODxml.h"
#include <string>
#define M_PI 3.14159265358979323846
#include <iostream>

using namespace std;
using namespace tinyxml2;

string PointValue2String(Point & point)
{
  string result("");
  char tmp[BUF_SIZE];
  sprintf(tmp, "%f%s",point.x,";");
  result.append(tmp);
  sprintf(tmp, "%f%s",point.y,";");
  result.append(tmp);
  sprintf(tmp, "%f",  point.z);
  result.append(tmp);
  return result;
}
Point String2PointValue(string & str)
{
  vector<double> vec;
  SplitString2Vector(vec, str, ";");
  return Point(vec[0],vec[1],vec[2]);
}
Point String2PointValue(const char* str)
{
  cout << "start data.origin \n";
  vector<double> vec;
  SplitString2Vector(vec, str, ";");
  cout << "end data.origin \n";
  if (3==vec.size())
    return Point(vec[0],vec[1],vec[2]);
  else
    return Point(0.0,0.0,0.0);
}

Point::Point (){}
Point::Point(double x_, double y_, double z_)
  :x(x_),y(y_),z(z_)
{
}

int File::write(const char* path, Bar &bar) {
	XMLDocument doc;
	doc.LoadFile( path );
	if ( doc.Error() )
    {
		printf( "error in %i: \n", doc.ErrorID() );
		printf( "Path: %s \n", path );
		exit( 1 );
    }
  
	XMLElement* barElement = doc.FirstChildElement( "BARS" )->FirstChildElement( "BAR" );
	barElement->SetAttribute( "ID" , 1 );
	barElement->SetAttribute( "origin", PointValue2String(bar.origin).c_str() );
	barElement->SetAttribute( "direction", PointValue2String(bar.direction).c_str() );
	barElement->SetAttribute( "length" , bar.length );
	barElement->SetAttribute( "width" , bar.width );
	barElement->SetAttribute( "numberOfStoreys" , bar.number_of_storeys );

	//barElement->SetAttribute( "concreteMass" , bar.sg_values[0] );


	//XMLNode* pointsNode = barElement->FirstChild();
	//pointsNode->DeleteChildren();

	////XMLElement 
	//for (int i = 0 ; i<data.points.size() ; i+=3 ) {
	//pointsNode->InsertEndChild( doc.NewElement( "POINT" ) );
	//XMLElement* pointElement = pointsNode->LastChildElement( "POINT" );
	//pointElement->SetAttribute( "x" , data.points[i+0] );
	//pointElement->SetAttribute( "y" , data.points[i+1] );
	//pointElement->SetAttribute( "z" , data.points[i+2] );
	//}

	//XMLElement* lengthElement = barElement->FirstChildElement( "LENGTH" );
	//XMLNode* length = lengthElement->FirstChild();
	//length->SetValue( data.get_length() );

	doc.SaveFile( path );

  return doc.ErrorID();
}

void File::read(const char* path, Bar &bar){
	tinyxml2::XMLDocument doc;
	doc.LoadFile( path );

	XMLElement* barElement = doc.FirstChildElement( "BARS" )->FirstChildElement( "BAR" );
	bar.origin = String2PointValue(barElement->Attribute( "origin" )) ;
	bar.direction = String2PointValue(barElement->Attribute( "direction" ));
	bar.length = barElement->DoubleAttribute( "length" );
	bar.width = barElement->DoubleAttribute( "width" );
	bar.number_of_storeys = barElement->IntAttribute( "numberOfStoreys" );

	//tinyxml2::XMLElement* titleElement = doc.FirstChildElement( "BARS" )->FirstChildElement( "BAR" );
	//const char* title = titleElement->GetText();
 //   printf( "Name of play (1): %s\n", title );

	//tinyxml2::XMLText* textNode = titleElement->FirstChild()->ToText();
 //   title = textNode->Value();
 //   printf( "Name of play (2): %s\n", title );

	//XMLNode* pointsNode = barElement->FirstChild();

	//XMLElement* pointElement = pointsNode->FirstChildElement( "POINT" );

	//data.points.clear();
	//
	//do {
	//data.points.push_back(pointElement->DoubleAttribute( "x" ));
	//data.points.push_back( pointElement->DoubleAttribute( "y" ));
	//data.points.push_back( pointElement->DoubleAttribute( "z" ));
	//} while (pointElement =  pointElement->NextSiblingElement( "POINT" ) );

	//for (pointElement ; pointElement ; pointElement =  pointsNode->NextSiblingElement( "POINT" ) ) {
	//data.points.push_back(pointElement->DoubleAttribute( "x" ));
	//data.points.push_back( pointElement->DoubleAttribute( "y" ));
	//data.points.push_back( pointElement->DoubleAttribute( "z" ));
	//}

  return;
}

int File::write(const char* path, Building &building) {
  XMLDocument doc;
  doc.LoadFile( path );
  if ( doc.Error() )
  {
    printf( "error in %i: \n", doc.ErrorID() );
    printf( "Path: %s \n", path );
    exit( 1 );
  }
  Bar bar;
  XMLElement* barsXml = doc.FirstChildElement( "BARS" );
  barsXml->DeleteChildren();
  //XMLElement* barElement = barsXml->FirstChildElement( "BAR" );


  ////XMLElement 
  for (unsigned int i = 0 ; i<building.Bars().size() ; i++ ) {
    barsXml->InsertEndChild( doc.NewElement( "BAR" ) );
    XMLElement* barElement = barsXml->LastChildElement( "BAR" );
    Bar& bar = building.BarAt(i);
    barElement->SetAttribute( "ID" , i+1 );
    barElement->SetAttribute( "origin", PointValue2String(bar.origin).c_str() );
    barElement->SetAttribute( "direction", PointValue2String(bar.direction).c_str() );
    barElement->SetAttribute( "length" , bar.length );
    barElement->SetAttribute( "width" , bar.width );
    barElement->SetAttribute( "numberOfStoreys" , bar.number_of_storeys );
    //for (int i = 0 ; i<bar.Points().size() ; i++ ) {
    //  Point& point = bar.Points()[i];
    //  barElement->InsertEndChild( doc.NewElement( "POINT" ) );
    //  XMLElement* pointElement = barElement->LastChildElement( "POINT" );
    //  pointElement->SetAttribute( "value", PointValue2String(point).c_str() );
    //}
  }

  barsXml->InsertEndChild( doc.NewElement( "SGDATA" ) );
  XMLElement* sgdataElement = barsXml->LastChildElement( "SGDATA" );
  sgdataElement->SetAttribute( "concreteVolume" , building.tot_vc );
  sgdataElement->SetAttribute( "reinforcementMass" , building.tot_mr );
  sgdataElement->SetAttribute( "profiledSheetingMass" , building.tot_mp );
  sgdataElement->SetAttribute( "structuralSteelMass" , building.tot_mq );
  sgdataElement->SetAttribute( "steelCoatingArea" , building.tot_aa );

  doc.SaveFile( path );

  return doc.ErrorID();
}

void File::read(const char* path, Building &building){
  tinyxml2::XMLDocument doc;
  doc.LoadFile( path );

  XMLElement* barsXml = doc.FirstChildElement( "BARS" );
  XMLElement* barElement = barsXml->FirstChildElement( "BAR" );
  building.Bars().clear();
  Bar bar;
  do {
    bar.origin = String2PointValue(barElement->Attribute( "origin" )) ;
    bar.direction = String2PointValue(barElement->Attribute( "direction" ));
    bar.length = barElement->DoubleAttribute( "length" );
    bar.width = barElement->DoubleAttribute( "width" );
    bar.number_of_storeys = barElement->IntAttribute( "numberOfStoreys" );
    building.Bars().push_back(bar);

    //XMLElement* pointElement = barElement->FirstChildElement( "POINT" );
    //bar.Points().clear();
    //do {
    //  bar.Points().push_back(String2PointValue(pointElement->Attribute( "value" )));
    //} while (pointElement =  pointElement->NextSiblingElement( "POINT" ) );
  } while (barElement =  barElement->NextSiblingElement( "BAR" ) );

  XMLElement* sgdataElement = barsXml->LastChildElement( "SGDATA" );
  //building.SgValues().resize(5);
  //building.SgValues()[0] = sgdataElement->DoubleAttribute( "concreteVolume" );
  //building.SgValues()[1] = sgdataElement->DoubleAttribute( "reinforcementMass" );
  //building.SgValues()[2] = sgdataElement->DoubleAttribute( "profiledSheetingMass" );
  //building.SgValues()[3] = sgdataElement->DoubleAttribute( "structuralSteelMass" );
  //building.SgValues()[4] = sgdataElement->DoubleAttribute( "steelCoatingArea" );

  building.tot_vc = sgdataElement->DoubleAttribute( "concreteVolume" );
  building.tot_mr = sgdataElement->DoubleAttribute( "reinforcementMass" );
  building.tot_mp = sgdataElement->DoubleAttribute( "profiledSheetingMass" );
  building.tot_mq = sgdataElement->DoubleAttribute( "structuralSteelMass" );
  building.tot_aa = sgdataElement->DoubleAttribute( "steelCoatingArea" );

  return;
}


Bar::Bar()
{
  direction.x = 0.0;direction.y = 0.0;direction.z = 0.0;
  origin.x = 0.0;origin.y = 0.0;origin.z = 0.0;
}

void Bar::set_default(void) {
	XMLDocument doc;

	static const char* xml = 
        "<?xml version=\"1.0\"?>"
        "<!DOCTYPE SOD SYSTEM \"SOD.dtd\">"
		"<BARS>"
        "<BAR id=\"1\">"
        "<NUMBEROFSTOREYS>0</NUMBEROFSTOREYS>"
		"<LENGTH>0</LENGTH>"
		"<WIDTH>0</WIDTH>"
        "</BAR>"
		"</BARS>";
	doc.Parse( xml );

	doc.SaveFile( "resources/test.xml" );
}

//void Data::dump_bars()
//{
//  for (int i=0;i<bars.size(); i++)
//  {
//    for (int j=0; j<bars[i].points.size(); j++)
//    {
//      cout << bars[i].points[j].x << ", ";
//      cout << bars[i].points[j].y << ", ";
//      cout << bars[i].points[j].z << "\n ";
//    }
//    cout << "\n";
//  }
//}


Building::Building()
{

}
